import React from 'react';
import styles from './Connect.m.less';
import commonStyles from './Common.m.less';
import { $t } from 'services/i18n';
import { Services } from 'components-react/service-provider';
import { injectState, useModule, mutation } from 'slap';
import { ExtraPlatformConnect } from './ExtraPlatformConnect';
import { EPlatformCallResult, TPlatform } from 'services/platforms';
import cx from 'classnames';
import * as remote from '@electron/remote';
import { OnboardingModule } from './Onboarding';
import PlatformLogo from 'components-react/shared/PlatformLogo';
import { EAuthProcessState } from 'services/user';
import { ListInput } from 'components-react/shared/inputs';
import Form from 'components-react/shared/inputs/Form';

export function Connect() {
  const {
    isRelog,
    selectedExtraPlatform,
    loading,
    authInProgress,
    authPlatform,
    setExtraPlatform,
  } = useModule(LoginModule);
  const { next } = useModule(OnboardingModule);
  const { UsageStatisticsService, OnboardingService, RecordingModeService } = Services;

  if (selectedExtraPlatform) {
    return <ExtraPlatformConnect />;
  }

  function onSkip() {
    if (loading || authInProgress) return;
    next();
  }

  function onSelectExtraPlatform(val: TExtraPlatform | 'tiktok' | undefined) {
    if (val === 'tiktok') {
      authPlatform('tiktok', afterLogin);
      return;
    }

    UsageStatisticsService.recordAnalyticsEvent('PlatformLogin', val);
    setExtraPlatform(val);
  }

  function afterLogin() {
    OnboardingService.actions.setExistingCollections();
    next();
  }

  const platforms = RecordingModeService.views.isRecordingModeEnabled
    ? ['streamlabs', 'youtube']
    : ['streamlabs', 'twitch', 'youtube', 'facebook', 'trovo', 'twitter'];

  return (
    <div className={styles.pageContainer}>
      <div className={styles.container}>
        <h1 className={commonStyles.titleContainer}>{$t('Connect')}</h1>
        {!isRelog && (
          <p style={{ marginBottom: 80 }}>
            {$t('Sign in with your content platform to get started with Streamlabs')}
          </p>
        )}
        {isRelog && (
          <h3 style={{ marginBottom: '16px' }}>
            {$t(
              'Your login has expired. Please reauthenticate to continue using Streamlabs Desktop.',
            )}
          </h3>
        )}
        <div className={styles.signupButtons}>
          {platforms.map((platform: TPlatform) => (
            <button
              className={cx(`button button--${platform}`, styles.loginButton)}
              disabled={loading || authInProgress}
              onClick={() => authPlatform(platform, afterLogin)}
              key={platform}
            >
              {loading && <i className="fas fa-spinner fa-spin" />}
              {!loading && (
                <PlatformLogo
                  platform={platform}
                  size="medium"
                  color={platform === 'trovo' ? 'black' : 'white'}
                />
              )}
            </button>
          ))}
        </div>
        <p className={styles['select-another']}> {$t('or select another platform')} </p>
        <Form layout="inline" style={{ width: 300 }}>
          <ListInput
            style={{ width: '100%' }}
            placeholder={$t('Select platform')}
            onChange={onSelectExtraPlatform}
            allowClear={true}
            value={selectedExtraPlatform}
            hasImage={true}
            options={[
              {
                value: 'tiktok',
                label: 'TikTok',
                image:
                  '',
              },
              {
                value: 'dlive',
                label: 'Dlive',
                image: require('../../../../media/images/platforms/dlive-logo-small.png'),
              },
              {
                value: 'nimotv',
                label: 'NimoTV',
                image: require('../../../../media/images/platforms/nimo-logo-small.png'),
              },
            ]}
          />
        </Form>
        <p>
          <br />
          <span className={styles['link-button']} onClick={onSkip}>
            {$t('Skip')}
          </span>
        </p>
      </div>
    </div>
  );
}

type TExtraPlatform = 'nimotv' | 'dlive';

export class LoginModule {
  state = injectState({
    selectedExtraPlatform: undefined as TExtraPlatform | undefined,
  });

  get UserService() {
    return Services.UserService;
  }

  get UsageStatisticsService() {
    return Services.UsageStatisticsService;
  }

  get isRelog() {
    return this.UserService.state.isRelog;
  }

  get loading() {
    return this.UserService.state.authProcessState === EAuthProcessState.Loading;
  }

  get authInProgress() {
    return this.UserService.state.authProcessState === EAuthProcessState.InProgress;
  }

  get isPartialSLAuth() {
    return this.UserService.views.isPartialSLAuth;
  }

  async authPlatform(platform: TPlatform | 'streamlabs', onSuccess: () => void, merge = false) {
    this.UsageStatisticsService.recordAnalyticsEvent('PlatformLogin', platform);

    if (platform === 'streamlabs') {
      await this.UserService.startSLAuth();
      onSuccess();
      return;
    }

    const result = await this.UserService.startAuth(
      platform,
      ['youtube', 'twitch', 'twitter'].includes(platform) ? 'external' : 'internal',
      merge,
    );

    if (result === EPlatformCallResult.TwitchTwoFactor) {
      remote.dialog
        .showMessageBox({
          type: 'error',
          message: $t(
            'Twitch requires two factor authentication to be enabled on your account in order to stream to Twitch. ' +
              'Please enable two factor authentication and try again.',
          ),
          title: $t('Twitch Authentication Error'),
          buttons: [$t('Enable Two Factor Authentication'), $t('Dismiss')],
        })
        .then(({ response }) => {
          if (response === 0) {
            remote.shell.openExternal('https://twitch.tv/settings/security');
          }
        });
    } else {
      // Currently we do not have special handling for generic errors
      onSuccess();
    }
  }

  async finishSLAuth(primaryPlatform?: TPlatform) {
    const result = await this.UserService.finishSLAuth(primaryPlatform);

    if (result === EPlatformCallResult.TwitchScopeMissing) {
      await remote.dialog.showMessageBox(remote.getCurrentWindow(), {
        type: 'warning',
        message: $t(
          'Streamlabs requires additional permissions from your Twitch account. Please log in with Twitch to continue.',
        ),
        title: 'Twitch Error',
        buttons: [$t('Refresh Login')],
      });

      // Initiate a Twitch merge to get permissions
      await this.authPlatform('twitch', () => {}, true);
    }

    return result;
  }

  @mutation()
  setExtraPlatform(val: TExtraPlatform | undefined) {
    this.state.selectedExtraPlatform = val;
  }
}
